package persistence

import (
	"fmt"
	"github.com/yejingxuan/accumulate/domain/entity"
	"gorm.io/gorm"
	"time"
)

type stockPersis struct {
	db *gorm.DB
}

func NewStockPersis(db *gorm.DB) *stockPersis {
	return &stockPersis{db}
}

//添加信息
func (s stockPersis) CreateStock(stock *entity.Stock) error {
	exist, err := s.GetStockInfoByCode(stock.Symbol)
	if exist.Symbol != "" {
		param := map[string]interface{}{
			"name":                 stock.Name,
			"type":                 stock.Type,
			"percent":              stock.Percent,
			"current":              stock.Current,
			"amplitude":            stock.Amplitude,
			"current_year_percent": stock.CurrentYearPercent,
			"market_capital":       stock.MarketCapital,
			"dividend_yield":       stock.DividendYield,
			"total_percent":        stock.TotalPercent,
			"percent5m":            stock.Percent5M,
			"income_cagr":          stock.IncomeCagr,
			"chg":                  stock.Chg,
			"eps":                  stock.Eps,
			"volume":               stock.Volume,
			"volume_ratio":         stock.VolumeRatio,
			"pb":                   stock.Pb,
			"followers":            stock.Followers,
			"turnover_rate":        stock.TurnoverRate,
			"first_percent":        stock.FirstPercent,
			"total_shares":         stock.TotalShares,
			"pe_ttm":               stock.PeTtm,
		}
		err = s.db.Table(entity.TableStock).Where("symbol = ?", stock.Symbol).Updates(param).Error
		return err
	}
	err = s.db.Table(entity.TableStock).Create(stock).Error
	return err
}

//更新清洗后的kline数据
func (s stockPersis) UpdateStockRecentKine(symbol, data string) error {
	param := map[string]interface{}{
		"recent_kline": data,
	}
	err := s.db.Table(entity.TableStock).Where("symbol = ?", symbol).Updates(param).Error
	return err
}

//更新标签
func (s stockPersis) UpdateStockTags(symbol, tags string) error {
	param := map[string]interface{}{
		"tags": tags,
	}
	err := s.db.Table(entity.TableStock).Where("symbol = ?", symbol).Updates(param).Error
	return err
}

//关注stock
func (s stockPersis) Follow(symbol string, serviceSymbol string, price float64, status string, date time.Time) error {

	if serviceSymbol != "" {
		param := map[string]interface{}{
			"read_price":  price,
			"read_status": status,
			"read_time":   date,
		}
		err := s.db.Table(entity.TableService).Where("service_symbol = ?", symbol).Updates(param).Error
		return err
	}
	service := &entity.Service{
		ServiceSymbol: symbol,
		ReadPrice:     price,
		ReadStatus:    status,
		ReadTime:      date,
	}
	err := s.db.Table(entity.TableService).Create(service).Error
	return err
}

//删除所有的基本数据
func (s stockPersis) DelAllStock() error {
	return s.db.Debug().Table(entity.TableStock).Where("1=1").Delete(nil).Error
}

//评论stock
func (s stockPersis) Comment(symbol string, comment string) error {
	param := map[string]interface{}{
		"comment": comment,
	}
	err := s.db.Table(entity.TableService).Where("service_symbol = ?", symbol).Updates(param).Error
	return err
}

//分页获取stock信息
func (s stockPersis) GetStockPageInfo(name string, symbol string, tags []string, status string, types []string, pageSize int,
	pageNo int, sortField string, sortOrder string) ([]entity.StockAllInfo, int, error) {
	var data []entity.StockAllInfo
	var count int64
	//条件拼装
	whereSql := " 1=1 "
	if name != "" {
		whereSql += " and name like '%" + name + "%' "
	}
	if symbol != "" {
		whereSql += " and symbol like '%" + symbol + "%' "
	}
	if tags != nil {
		for _, tag := range tags {
			whereSql += " and tags like '%" + tag + "%' "
		}
	}
	if status != "" {
		whereSql += " and read_status = '" + status + "' "
	}
	if types != nil && len(types) > 0 {
		whereSql += " and ( "
		for idx, item := range types {
			if idx == 0 {
				whereSql += " symbol like '" + item + "%' "
			} else {
				whereSql += " or symbol like '" + item + "%' "
			}
		}
		whereSql += " )"
	}

	//排序
	sortSql := "symbol asc"
	sortFieldMap := map[string]string{
		"symbol":             "symbol",
		"marketCapital":      "market_capital",
		"percent":            "percent",
		"currentYearPercent": "current_year_percent",
		"dividendYield":      "dividend_yield",
	}
	if sortField != "" && sortOrder != "" && sortFieldMap[sortField] != "" {
		sortSql = fmt.Sprintf("%s %s", sortFieldMap[sortField], sortOrder)
	}

	//执行查询
	err := s.db.Debug().Table(entity.TableStock).
		Joins("left join " + entity.TableService + " t2 on t2.service_symbol = " + entity.TableStock + ".symbol").
		Where(whereSql).Order(sortSql).Limit(pageSize).Offset((pageNo - 1) * pageSize).Scan(&data).Error
	if err != nil {
		return data, int(count), err
	}
	//总数计算
	err = s.db.Table(entity.TableStock).
		Joins("left join " + entity.TableService + " t2 on t2.service_symbol = " + entity.TableStock + ".symbol").
		Where(whereSql).Count(&count).Error
	return data, int(count), err
}

//获取详情
func (s stockPersis) GetStockInfoByCode(code string) (*entity.StockAllInfo, error) {
	res := entity.StockAllInfo{}
	err := s.db.Debug().Table(entity.TableStock).
		Joins("left join "+entity.TableService+" t2 on t2.service_symbol = "+entity.TableStock+".symbol").
		Where(entity.TableStock+".symbol = ?", code).Scan(&res).Error
	return &res, err
}
